package com.example.scg.route.generator;

import com.example.scg.route.generator.config.RetryConfig;
import java.util.HashMap;
import java.util.Map;
import javax.validation.constraints.NotNull;
import org.springframework.cloud.gateway.filter.FilterDefinition;

/**
 * <b>Retry过滤器定义生成器，只支持GET方法</b>
 * <pre>
 * <b>重试GatewayFilter工厂支持以下参数：</b>
 *
 * retries：应尝试的重试次数。
 *
 * statuses：应重试的HTTP状态代码，以表示{@link org.springframework.http.HttpStatus}。
 *
 * methods：应该重试的HTTP方法，以表示{@link org.springframework.http.HttpMethod}。
 *
 * series：要重试的一系列状态代码，使用表示{@link org.springframework.http.HttpStatus.Series}。
 *
 * exceptions：应重试的引发异常的列表。
 *
 * backoff：为重试配置的指数补偿。重试在的退避间隔后执行firstBackoff * (factor ^ n)，其中n为迭代。如果maxBackoff已配置，则应用的最大退避限制为maxBackoff。如果basedOnPreviousValue为true，则使用计算退避prevBackoff * factor。
 * backoff: he configured exponential backoff for the retries. Retries are performed after a backoff interval of firstBackoff * (factor ^ n), where n is the iteration. If maxBackoff is configured, the maximum backoff applied is limited to maxBackoff. If basedOnPreviousValue is true, the backoff is calculated by using prevBackoff * factor.
 * <b>Retry如果启用了，则以下为默认过滤器配置：</b>
 *
 * retries：3次
 *
 * series：5XX系列
 *
 * methods：GET方法
 *
 * exceptions：IOException和TimeoutException
 *
 * backoff：禁用
 *
 * <b>The following defaults are configured for Retry filter, if enabled:</b>
 *
 * retries: Three times
 *
 * series: 5XX series
 *
 * methods: GET method
 *
 * exceptions: IOException and TimeoutException
 *
 * backoff: disabled
 *
 * </pre>
 *
 * CreateTime: 2020-01-12
 *
 * @author HuangZhongHui
 **/
public class RetryFilterGenerator {

  /**
   * 过滤器名称，该过滤器工厂为:{@link org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory}
   */
  public static final String FILTER_NAME = "Retry";

  /**
   * 生成路由过滤器定义
   *
   * @param retryConfig Retry参数
   * @return 路由过滤器定义
   */
  public static FilterDefinition create(@NotNull RetryConfig retryConfig) {
    FilterDefinition definition = new FilterDefinition();
    definition.setName(FILTER_NAME);
    Map<String, String> args = new HashMap<>(8);
    retryConfig.fillConfMap(args);
    definition.setArgs(args);
    return definition;
  }
}
